//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package common;

import lib.netrxtx.TCPPort;
import lib.netrxtx.TCPPortEvent;
import lib.netrxtx.TCPPortEventListener;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class SocksProxy implements TCPPortEventListener {
    private TCPPort port;
    private final String pserver;
    private final String pport;
    private final String ipaddress;
    private final String ipport;
    private final byte socksVer = 5;
    private final boolean logState;
    private int readIndex;
    List<byte[]> received = new ArrayList();
    private String serverStreamAddr;
    private String serverStreamPort;
    public SocksProxy.state proxyState;

    public SocksProxy(String pserver, String pport, String ipaddress, String ipport, boolean logState) {
        this.pserver = pserver;
        this.pport = pport;
        this.ipaddress = ipaddress;
        this.ipport = ipport;
        this.proxyState = SocksProxy.state.initial;
        this.logState = logState;
    }

    public SocksProxy.state getState() {
        return this.proxyState;
    }

    public TCPPort getTcpPort() {
        TCPPort rval = this.port;
        this.port = null;
        return rval;
    }

    public String getRelayAddr() {
        return this.serverStreamAddr;
    }

    public String getRelayPort() {
        return this.serverStreamPort;
    }

    public void reconnect() throws Exception {
        this.serverStreamAddr = null;
        this.serverStreamPort = null;
        this.resetInput();
        if(this.port != null && this.port.isConnected()) {
            this.port.stop();
        } else {
            this.port = new TCPPort(this.pserver, Integer.valueOf(this.pport).intValue());
            this.port.notifyOnDataAvailable(true);
            this.port.addEventListener(this);
        }

        this.port.connect();
        this.proxyState = SocksProxy.state.connecting;
        byte[] cmd = new byte[]{(byte)5, (byte)1, (byte)0};
        this.write(cmd);
        if(this.logState) {
            System.out.println("SocksProxy: send handshake to " + this.pserver + ":" + this.pport);
        }

    }

    public void resetInput() {
        List var1 = this.received;
        synchronized(this.received) {
            this.readIndex = 0;
            this.received.clear();
        }
    }

    public int available() {
        int rval = 0;
        List var2 = this.received;
        synchronized(this.received) {
            Iterator var4 = this.received.iterator();

            while(true) {
                if(!var4.hasNext()) {
                    break;
                }

                byte[] msg = (byte[])var4.next();
                rval += msg.length;
            }
        }

        if(this.readIndex > 0) {
            rval -= this.readIndex;
        }

        return rval;
    }

    public byte[] read() {
        int size = this.available();
        byte[] rval = new byte[size];
        List var3 = this.received;
        synchronized(this.received) {
            int dstIndex = 0;
            int i = 0;

            while(true) {
                if(i >= this.received.size()) {
                    break;
                }

                byte[] rd = (byte[])this.received.get(i);
                int srcIndex;
                int srcLen;
                if(i == 0 && this.readIndex > 0) {
                    srcIndex = this.readIndex;
                    srcLen = rd.length - this.readIndex;
                } else {
                    srcIndex = 0;
                    srcLen = rd.length;
                }

                System.arraycopy(rd, srcIndex, rval, dstIndex, srcLen);
                dstIndex += srcLen;
                ++i;
            }
        }

        this.resetInput();
        return rval;
    }

    public void write(byte[] wb) throws IOException {
        OutputStream os = this.port.getOutputStream();
        os.write(wb);
    }

    public void write(byte[] wb, int index, int size) throws IOException {
        OutputStream os = this.port.getOutputStream();
        os.write(wb, index, size);
    }

    public void stop() {
        try {
            if(this.port != null && this.port.isConnected()) {
                this.port.stop();
            }

            this.resetInput();
        } catch (Exception var2) {
            var2.printStackTrace();
        }

    }

    public void tcpPortEvent(TCPPortEvent ev) {
        try {
            if(this.port == null) {
                return;
            }

            if(ev.getEventType() == 1) {
                InputStream e = this.port.getInputStream();
                if(e.available() >= 2) {
                    byte[] hdr;
                    byte[] body;
                    int len;
                    switch(this.proxyState.ordinal()) {
                        case 1:
                            byte[] var9 = new byte[2];
                            e.read(var9);
                            if(var9[0] == 5 && var9[1] == 0) {
                                if(this.logState) {
                                    System.out.println("SocksProxy: handshake done.");
                                }

                                hdr = this.ipaddress.getBytes();
                                body = new byte[7 + hdr.length];
                                len = 5 + hdr.length;
                                int tcpport = Integer.valueOf(this.ipport).intValue();
                                body[0] = 5;
                                body[1] = 1;
                                body[2] = 0;
                                body[3] = 3;
                                body[4] = (byte)hdr.length;
                                System.arraycopy(hdr, 0, body, 5, hdr.length);
                                body[len++] = (byte)(tcpport >> 8);
                                body[len] = (byte)tcpport;
                                this.proxyState = SocksProxy.state.connected;
                                this.write(body);
                                if(this.logState) {
                                    System.out.println("SocksProxy: connect request to " + (hdr[0] & 255) + "." + (hdr[1] & 255) + "." + (hdr[2] & 255) + "." + (hdr[3] & 255) + ":" + tcpport);
                                }
                            }
                            break;
                        case 2:
                            if(e.available() >= 4) {
                                Integer bindPort = null;
                                hdr = new byte[4];
                                e.read(hdr);
                                if(hdr[0] == 5 && hdr[1] == 0) {
                                    if(this.logState) {
                                        System.out.println("SocksProxy: connected.");
                                    }

                                    body = new byte[e.available()];
                                    e.read(body);
                                    switch(hdr[3]) {
                                        case 1:
                                            this.serverStreamAddr = String.valueOf(body[0] & 255) + "." + (body[1] & 255) + "." + (body[2] & 255) + "." + (body[3] & 255);
                                            bindPort = Integer.valueOf(body[4] << 8 & '\uff00' | body[5] & 255);
                                        case 2:
                                        default:
                                            break;
                                        case 3:
                                            len = body[0] & 255;
                                            this.serverStreamAddr = new String(body, 1, len);
                                            bindPort = Integer.valueOf(body[len + 1] << 8 & '\uff00' | body[len + 2] & 255);
                                    }

                                    if(bindPort != null) {
                                        this.serverStreamPort = String.valueOf(bindPort.intValue());
                                    }

                                    if(bindPort.intValue() == 0) {
                                        this.serverStreamAddr = this.pserver;
                                        this.serverStreamPort = this.pport;
                                        this.proxyState = SocksProxy.state.relaySameAddr;
                                    } else {
                                        this.proxyState = SocksProxy.state.relay;
                                        this.port.stop();
                                    }
                                }
                            }
                            break;
                        default:
                            this.port.stop();
                            this.proxyState = SocksProxy.state.initial;
                            throw new IOException("SocksProxy: error: state inconsistent.");
                    }
                }
            }

            if(ev.getEventType() == 4) {
                if(this.port != null && this.port.isConnected()) {
                    this.port.stop();
                }

                this.proxyState = SocksProxy.state.initial;
                throw new IOException("SocksProxy: server disconnected.");
            }
        } catch (Exception var8) {
            Utils.logException(var8, " SocksProxy: ");
        }

    }

    public static enum state {
        connecting,
        connected,
        relay,
        relaySameAddr,
        initial;

        private state() {
        }
    }
}
